/*
问题描述：对于给定的一个表达式，表达式中可以包括常数、算术运行符（包括：“+”、“-”、“*”、“/”、“%”（求余运算）、
“^”（乘幂运算）、“！”（阶乘运算））和括号，编写一个简单计算器，实现表达式的计算。

基本要求：从键盘输入一个正确的表达式，将表达式转换为对应的后缀表达式，并计算后缀表达式的值。对于表达式中的简单错误
（如，除数不能为零、负数无法求阶乘等），能够给出提示，并给出错误信息；表达式中可以包括单个字母表示的变量。

测试数据：任意选取一个符合题目要求的表达式。

提高要求：完成基本要求的基础上，能够支持一部分不规范的表达式（如，3-3+-6），支
持科学计数法表示的数（如，19971400000000表示为：1.99714E13），并具有图形用户界面的简单计算器。

考核要求：
（1）表达式中的数据可以是整数或小数，达到基本要求，成绩为良好。但是，如果仅能处理个位数，成绩为及格；
如果仅能处理整数，成绩为中等。
(2)在达到基本要求的基础之上，完成提高要求，成绩可以为优秀。
*/
#include <iostream> 
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string>
using namespace std;

class Expression
{
	public:
		Expression(string str); //构造函数
        ~Expression( ); //析构函数
        double Compute( ); //计算表达式str的值
    private:
        int Comp(char str1, char str2); //比较str1的str2优先级
        string str;
};

Expression :: Expression(string str) //接收键盘输入并加上定界符
{
	this->str = str + "#";
}

Expression :: ~Expression( )
{

}

double Expression :: Compute( )
{
	char OPND[100], OPTR[100]; //定义两个顺序栈
	char ex[100];   //定义字符串数组用于存放转换后的数字串 
    OPTR[0] = '#'; //栈OPTR初始化为定界符
    int top1 = -1, top2 = 0; //初始化栈OPND和OPTR的栈顶指针
    int i, k, op;
    double x,y,z;
    double num=0;

    for (i = 0; str[i] != '\0'; ) //依次扫描每一个字符
    { 
    	if (str[i] >= 48 && str[i] <= 57||str[i] == '.') //数字0的ASCII码是48或是小数点(46) 
    	{
    		OPND[++top1]=str[i++] - 48; //将字符型数字转换后压栈 
    	}
    	else if(str[i] == '!')   //单独计算阶乘 
    	{
    		k = Comp(str[i], OPTR[top2]);
            if (k == 1) //str[i]的优先级高
            {
            	OPTR[++top2] = str[i++]; //将str[i]压入运算符栈
            }
            else if (k == -1) //str[i]的优先级低
            {
            	x = OPND[top1--]; //从运算对象栈出栈一个元素
                op = OPTR[top2--]; //从运算符栈出栈一个元素
                
                z=1;
				for(int t=1;t<x;t++)
				{
					z=x*x;
					x--;
				}
				OPND[++top1] = z; //运算结果入运算对象栈
        	}
            else
			{ //str[i]与运算符栈的栈顶元素优先级相同
				top2--; //匹配str[i]，扫描下一个字符
				i++;
			}
    	}
        else   //剩下的运算符情况 
        {
        	k = Comp(str[i], OPTR[top2]);
            if (k == 1) //str[i]的优先级高
            {
            	OPTR[++top2] = str[i++]; //将str[i]压入运算符栈
            }
            else if (k == -1) //str[i]的优先级低
            {
            	y = OPND[top1--]; //从运算对象栈出栈两个元素
                x = OPND[top1--];
                op = OPTR[top2--]; //从运算符栈出栈一个元素

                switch (op) // op为运算符，进行相应运算
                {
                	case '+': z = x + y; break;
                    case '-': z = x - y; break;
                    case '*': z = x * y; break;
 					case '/':
 						if(y!=0)
 						{
 							z = x / y;
 						}
 						else
 						{
 							cout<<"除数不能为零，这么低级的错误都犯？！";
 						}
					  break;
 					case '%': z = fmod(x,y); break;
 					case '^':
 						z = 1;
					 for(int i=0;i<y;i++)
					 {
					 	z = z * x;
					 } 
					 break;
					default: break;
				}
				OPND[++top1] = z; //运算结果入运算对象栈
			}
			else
			{ //str[i]与运算符栈的栈顶元素优先级相同
				top2--; //匹配str[i]，扫描下一个字符
				i++;
			}
		}
	}
	return OPND[top1]; //运算对象栈的栈顶元素即为运算结果
}

int Expression :: Comp(char str1, char str2)
{ //比较str1和str2的优先级，1：str1高；0：相同；-1：str1低
	switch (str1)
	{
		case '+': case '-': if (str2 == '(' || str2 == '#') return 1; else return -1;
		break;
		case '*': case '/':case '%' :if (str2 == '('||str2 == '#'||str2 == '+'||str2 == '-') return 1; else return -1;
		break;
		case '^':case '!':if(str2 == '^'||str2 == '!') return -1; else return 1;
		case '(': return 1; break;
		case ')': if (str2 == '(') return 0; else return -1;
		break;
		case '#': if (str2 == '#') return 0; else return -1;
		break;
		default: break;
	}
}
int main( )
{
	string str;
	while(1)
	{
		cout << "请输入一个表达式：" << endl;
	    cin >> str;
		Expression E{str}; //定义对象变量E
		double result = E.Compute( ); //result保存计算结果
		cout << "表达式的值是：" << result << endl;
	}
	return 0;
}